<!-- 设备巡检-巡检规则-新增/编辑/复制页面 -->
<template>
  <div class="add-equip-detail">
    <div class="add-equip-content">
      <px-button style="margin-top: 16px; margin-bottom: 16px" type="primary" icon="ArrowLeft" @click="cancelMainPage">返回</px-button>
      <px-scrollbar class="add-equip-body">
        <px-form ref="formRef" :inline="true" :model="formValue" :rules="rules" label-position="right" label-width="120px">
          <EditDropDown dropdownTitle="基础信息" style="margin-top: 0">
            <template v-slot:content>
              <div>
                <px-row>
                  <px-col :span="6">
                    <px-form-item label="巡检规则编号" prop="ruleCode">
                      <px-input v-model="formValue.ruleCode" placeholder="请输入规则编号" maxlength="50" clearable disabled />
                    </px-form-item>
                  </px-col>
                  <px-col :span="6">
                    <px-form-item label="巡检规则名称" prop="ruleName">
                      <px-input v-model="formValue.ruleName" placeholder="请输入规则名称" maxlength="50" clearable />
                    </px-form-item>
                  </px-col>
                  <px-col :span="6">
                    <px-form-item label="巡检类型" prop="inspectType">
                      <px-radio-group v-model="formValue.inspectType">
                        <px-radio v-for="item in inspectTypeList" :key="item.value" :label="item.value">{{ item.label }}</px-radio>
                      </px-radio-group>
                    </px-form-item>
                  </px-col>
                  <px-col :span="6">
                    <EquipClassSelect :isRequired="true" :className="formValue.className" @changeClassName="changeClassName" />
                  </px-col>
                  <px-col :span="24">
                    <px-form-item label="备注" prop="remark">
                      <px-input v-model="formValue.remark" :rows="3" type="textarea" placeholder="请输入备注" maxlength="1000" clearable />
                    </px-form-item>
                  </px-col>
                </px-row>
              </div>
            </template>
          </EditDropDown>
          <EditDropDown dropdownTitle="巡检设置">
            <template v-slot:content>
              <div class="block w-[100%]">
                <px-row>
                  <px-col :span="12">
                    <px-form-item label="巡检区域" prop="inspectArea" :rules="{ required: true, message: '请选择巡检区域', trigger: 'change' }">
                      <px-cascader
                        ref="cascaderRef"
                        v-model="formValue.inspectArea"
                        filterable
                        clearable
                        style="width: 100%"
                        :options="positionCodesList"
                        :props="cascaderProps"
                        placeholder="请选择巡检区域"
                        @focus="focusPositionCodes"
                        @change="changeCheckArea"
                      />
                    </px-form-item>
                  </px-col>
                  <px-col :span="12">
                    <px-form-item label="巡检内容" prop="inspectContentTypes">
                      <px-checkbox-group v-model="formValue.inspectContentTypes" @change="changeInspectContentTypes">
                        <px-checkbox v-for="item in inspectContentTypesList" :key="item.value" :label="item.value">{{ item.label }}</px-checkbox>
                      </px-checkbox-group>
                    </px-form-item>
                  </px-col>
                </px-row>
                <px-row :gutter="22">
                  <px-col :span="24">
                    <px-form-item label="巡检项目" prop="tableData" class="_form-rules">
                      <px-button type="primary" ghost class="mb-[10px]" @click="handleSelectRules">选择巡检项模版</px-button>
                      <InspectRulesTable :table-data="tableData" :tableColumns="tableColumns" :total="0" class="w-[100%]" @del="deleteSelected" />
                    </px-form-item>
                  </px-col>
                </px-row>
              </div>
            </template>
          </EditDropDown>
          <EditDropDown v-if="formValue.inspectContentTypes.includes(1)" dropdownTitle="巡检设备">
            <template v-slot:content>
              <div class="w-[100%]">
                <px-row :gutter="22">
                  <px-col :span="24">
                    <px-button type="primary" ghost class="mb-[10px]" @click="handleSelectEquip">选择设备</px-button>
                    <px-form-item label-width="0px" label="" prop="taskEqpRelationDTOS">
                      <InspectRulesTable
                        :table-data="tableEqiupSelected"
                        :tableColumns="tableEqiupColums"
                        :total="0"
                        row-key="eqpId"
                        :hasDrag="true"
                        class="w-[100%]"
                        @on-drag="tableEqiupDrag"
                        @del="deleteEquipSelected"
                      />
                    </px-form-item>
                  </px-col>
                </px-row>
              </div>
            </template>
          </EditDropDown>
          <PreviewForm v-if="previewVisible" v-model="ruleContent" :formValue="formValue" /> </px-form
      ></px-scrollbar>
    </div>
    <div class="info-form-btns">
      <px-button @click="cancelMainPage">取消</px-button>
      <px-button type="primary" @click="handleSubmit(formRef)">保存</px-button>
    </div>
    <SelectInspectRules
      v-if="isDialogView"
      v-model:is-view="isDialogView"
      :multiple="true"
      :className="formValue.className"
      :inspectArea="positionCodes"
      :inspectContentTypes="formValue.inspectContentTypes"
      @select-items="selectTreeItems"
    />
    <SelectInspectEquip
      v-if="isAddEquip"
      v-model:is-view="isAddEquip"
      :multiple="true"
      :className="formValue.className"
      :inspectArea="formValue.inspectArea"
      :equipFilters="equipFilters"
      @select-items="selectEquipItems"
    />
    <px-drawer v-model="innerDrawer" :append-to-body="true" size="50%" :with-header="false">
      <TemplateDetail v-if="innerDrawer" :id="templateId" type="comp" />
      <template #footer>
        <px-button @click="innerDrawer = false">关闭</px-button>
      </template>
    </px-drawer>
  </div>
</template>
<script setup lang="ts">
import { querySystemSelect } from "@/api/equip/archive";
import { getInspectRule, getPreviewTemplateItem, getRuleCode, saveInspectRule, updateInspectRule } from "@/api/equip/inspectRule";
import { getTableData } from "@/api/system/positionManage";
import EditDropDown from "@/views/all/equip/components/EditDropDown.vue";
import EquipClassSelect from "@/views/all/equip/components/EquipClassSelect.vue";
import { cloneDeep, debounce } from "@pureadmin/utils";
import { PxMessage, PxMessageBox } from "px-ui";
import { computed, onMounted, reactive, ref, toRefs, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { INSPECT_CONTENT, INSPECT_TYPE } from "../../config";
import TemplateDetail from "../../templates/ViewInspecDetail.vue";
import { TableItem } from "../../types";
import { INSPECT_RULE_DEFAULT_FORMVALUE, INSPECT_RULE_EQUIP_TABLE_COLUMNS, showTemplateDetail } from "../config";
import { useAction } from "../hooks";
import InspectRulesTable from "./InspectRulesTable.vue";
import PreviewForm from "./PreviewForm.vue";
import SelectInspectEquip from "./SelectInspectEquip.vue";
import SelectInspectRules from "./SelectInspectRules.vue";
const router = useRouter();
const route = useRoute();
const actions = useAction();

const tableEqiupColums = ref<TableItem[]>(INSPECT_RULE_EQUIP_TABLE_COLUMNS);
const cascaderProps = {
  children: "children",
  label: "name",
  value: "id",
  checkStrictly: true
};
const cascaderRef = ref();
// 模板详情相关
const innerDrawer = ref(false); // 抽屉是否显示
const templateId = ref(); // 模板id
const getTemplateId = id => {
  innerDrawer.value = true;
  templateId.value = id;
};
const columns = showTemplateDetail(getTemplateId);
const tableColumns = ref<TableItem[]>(columns);
// 页面本身的值
const state = reactive<any>({
  formRef: null,
  isAddEquip: false,
  isDialogView: false,
  tableData: [], //巡检项目
  tableEqiupSelected: [], //巡检设备
  formValue: { ...INSPECT_RULE_DEFAULT_FORMVALUE }, // 基础信息form表单
  inspectContentTypesList: INSPECT_CONTENT, // 基础信息巡检内容列表
  inspectTypeList: INSPECT_TYPE, // 基础信息巡检类型列表
  positionCodesList: [], // 基础信息巡检区域列表
  positionCodes: [],
  systemList: [],
  ruleContent: {}
});
const {
  formRef,
  formValue,
  positionCodesList,
  positionCodes,
  inspectContentTypesList,
  inspectTypeList,
  isAddEquip,
  isDialogView,
  tableData,
  tableEqiupSelected,
  systemList,
  ruleContent
} = toRefs(state);
// 规则预览是否可见
const previewVisible = computed(() => {
  return ruleContent.value?.contentDTOList?.length > 0 || ruleContent.value?.eqpContentDTOList?.length > 0;
});
const inspectTemCodeList = computed(() => {
  return tableData.value?.reduce((pre, cur) => {
    return [...pre, cur.temCode];
  }, []);
});
const eqpIdList = computed(() => {
  return tableEqiupSelected.value?.reduce((pre, cur) => {
    return [...pre, cur.eqpId];
  }, []);
});
const queryPreviewTemplateItem = async params => {
  ruleContent.value = [];
  const data = await getPreviewTemplateItem(params);
  if (data) {
    ruleContent.value = data;
  }
};
const handleRuleContentByInspectContentTypes = debounce(() => {
  const { inspectContentTypes } = formValue.value;
  // a、巡检内容已选择，且巡检模板不为空
  if (inspectContentTypes?.length > 0 && inspectTemCodeList.value?.length > 0) {
    if (inspectContentTypes.length === 1 && inspectContentTypes[0] === 1) {
      // 1、仅设备巡检,巡检模板和巡检设备都存在，才获取预览内容,否则清空
      if (eqpIdList.value.length > 0) {
        queryPreviewTemplateItem({
          temCodes: inspectTemCodeList.value,
          eqpIdList: eqpIdList.value
        });
      }
    } else {
      //2、存在环境巡检，巡检模板存在，就可获取预览内容
      queryPreviewTemplateItem({
        temCodes: inspectTemCodeList.value,
        eqpIdList: eqpIdList.value
      });
    }
  } else {
    // b、巡检内容未选择，或巡检模板为空
    ruleContent.value = {};
  }
}, 500);
const oldPrams = ref("");
// 监听：监听模板与设备变化，获取预览内容
watch(
  () => [inspectTemCodeList, eqpIdList],
  () => {
    const newParams = JSON.stringify(inspectTemCodeList.value) + JSON.stringify(eqpIdList.value);
    if (newParams !== oldPrams.value) {
      handleRuleContentByInspectContentTypes();
    }
    oldPrams.value = JSON.stringify(inspectTemCodeList.value) + JSON.stringify(eqpIdList.value);
  },
  {
    deep: true
  }
);
// 巡检设备的当前模板巡检条件,用于模板变化时删除不符合条件的巡检设备
const equipFilters = computed(() => {
  const filters = {
    systemCode: [],
    typeId: [],
    categoryId: []
  };
  Object.keys(filters).forEach(key => {
    tableData.value.forEach(item => {
      const value = item[key];
      if (!filters[key].includes(value) && item[key]) {
        filters[key].push(value);
      }
    });
  });
  return filters;
});
// 监听：监听模板变化，筛选设备
watch(
  () => [equipFilters, tableData.value.length],
  () => {
    if (tableData.value.length === 0) {
      tableEqiupSelected.value = [];
    } else {
      Object.keys(equipFilters.value).forEach(key => {
        const arr = equipFilters.value[key];
        if (key === "systemCode") {
          filterSystemList(systemList.value, arr);
        }
        if (arr.length > 0) {
          tableEqiupSelected.value = tableEqiupSelected.value.filter(item => {
            return item[key] && arr.includes(item[key]);
          });
        }
      });
    }
  },
  {
    deep: true
  }
);
// 表单校验规则
const rules = computed(() => ({
  ruleCode: [{ required: true, message: "巡检规则不能为空", trigger: "blur" }],
  ruleName: [{ required: true, message: "巡检规则名称不能为空", trigger: "blur" }],
  inspectType: [{ required: true, message: "巡检类型不能为空", trigger: "change" }],
  inspectContentTypes: [{ required: true, message: "巡检内容不能为空", trigger: "change" }],
  tableData: [
    //需要自定义规则
    {
      required: true,
      validator: validateRulesTable,
      trigger: "change"
    }
  ],
  taskEqpRelationDTOS: [
    {
      required: true,
      validator: validateEqpTable,
      trigger: "change"
    }
  ]
}));

const validateRulesTable = (rule: any, value: any, callback: any) => {
  if (!tableData.value || tableData.value?.length === 0) {
    callback(new Error("请选择巡检项目"));
  } else {
    callback();
  }
};
const validateEqpTable = (rule: any, value: any, callback: any) => {
  if (!tableEqiupSelected.value || tableEqiupSelected.value?.length === 0) {
    callback(new Error("请选择巡检设备"));
  } else {
    callback();
  }
};
const getPreviewItem = (contentDTOList, eqpContentDTOList) => {
  // 延时赋值——覆盖因模板和设备变化引发的预览接口调用响应数据
  setTimeout(() => {
    // 条件判断——解决延时期间，预览内容相关条件变动引发的副作用
    const { inspectContentTypes } = formValue.value;
    // 巡检内容已选择，且巡检模板不为空
    if (inspectContentTypes?.length > 0 && inspectTemCodeList.value?.length > 0) {
      if (inspectContentTypes.length === 1 && inspectContentTypes[0] === 1) {
        // 1、仅设备巡检,巡检模板和巡检设备都存在，才获取预览内容,否则清空
        if (eqpIdList.value.length > 0) {
          ruleContent.value.eqpContentDTOList = eqpContentDTOList;
        }
      } else {
        //2、存在环境巡检，巡检模板存在，就可获取预览内容
        ruleContent.value = { contentDTOList, eqpContentDTOList };
      }
    }
  }, 2000);
};
const getDetail = async () => {
  const {
    query: { id },
    path
  } = route;
  if (id) {
    const dataDetail: any = await getInspectRule({ id, isShowContent: true });
    const { templateDTOList, eqpDTOList, contentDTOList, eqpContentDTOList, id: dataId, ...others } = dataDetail;
    if (path === "/all/equip/inspect/rule/edit") {
      // 1、编辑页面
      formValue.value = { ...others, id: dataId };
      getPreviewItem(contentDTOList, eqpContentDTOList);
    }
    if (path === "/all/equip/inspect/rule/copy") {
      // 2、复制页面
      const data = await getRuleCode();
      formValue.value = { ...others, ruleCode: data };
      getPreviewItem(contentDTOList, eqpContentDTOList);
    }
    tableEqiupSelected.value = eqpDTOList;
    tableData.value = templateDTOList;

    // 获取区域信息
    await focusPositionCodes();
    positionCodes.value = getInspectAreaCodes(formValue.value.inspectArea);
  }
  if (path === "/all/equip/inspect/rule/add") {
    // 3、新增页面
    const data = await getRuleCode();
    formValue.value.ruleCode = data;
  }
};
const addSystemCode = (arr, codes) => {
  arr.forEach(item => {
    codes.push(item.code);
    if (item.children) {
      addSystemCode(item.children, codes);
    }
  });
};
const filterSystemList = (arr, codes) => {
  const { systemCode } = equipFilters.value;
  arr.forEach(item => {
    if (systemCode.includes(item.code)) {
      codes.push(item.code);
      item.children && addSystemCode(item.children, codes);
    } else if (item.children) {
      filterSystemList(item.children, codes);
    }
  });
};
const getSystemList = async () => {
  const tempSystemList: any = await querySystemSelect({});
  systemList.value = tempSystemList || [];
};
onMounted(() => {
  getSystemList();
  getDetail();
});

// 外部封装好的组件
// 科室组件调用父组件
const changeClassName = (val, isOnlyClass) => {
  formValue.value.className = val;
  if (!isOnlyClass) {
    clearFields(["tableData", "tableEqiupSelected"]);
  }
  // // 内容改变，清空ruleContent
  // ruleContent.value = null;
};
// 获取巡检区域
const focusPositionCodes = async () => {
  const data = await getTableData({});
  positionCodesList.value = data || [];
};
// 巡检区域改变
const changeCheckArea = val => {
  formValue.value.inspectArea = val && val.length > 0 ? val[val.length - 1] : "";
  positionCodes.value = getInspectAreaCodes(formValue.value.inspectArea);
  clearFields(["tableData", "tableEqiupSelected"]);
  cascaderRef.value.togglePopperVisible(false);
  // // 内容改变，清空ruleContent
  // ruleContent.value = null;
};
// 巡检内容改变
const changeInspectContentTypes = val => {
  tableData.value = tableData.value.filter(item => val.includes(item["inspectContentType"]));
  // // 内容改变，清空ruleContent
  // ruleContent.value = null;
};
// 移除巡检模板
function deleteSelected(row) {
  tableData.value = tableData.value.filter(item => item["id"] !== row["id"]);
  // 内容改变，清空ruleContent
  ruleContent.value = null;
}
// 选择巡检模板
function handleSelectRules() {
  if (formValue.value.inspectContentTypes?.length === 0 || !formValue.value.className || !formValue.value.inspectArea) {
    formRef?.value.validateField("inspectContentTypes");
    formRef?.value.validateField("className");
    formRef?.value.validateField("inspectArea");
  } else {
    isDialogView.value = true;
  }
}
// 选中巡检模板
function selectTreeItems(val) {
  tableData.value = mergeAndDeduplicate(tableData.value || [], val, "id");
  // 内容改变，清空ruleContent
  // ruleContent.value = null;
  if (tableData.value.length > 0) {
    formRef?.value.clearValidate("tableData");
  }
}
// 选择巡检设备
function handleSelectEquip() {
  const { className, inspectArea } = formValue.value;
  if (className && inspectArea && inspectTemCodeList.value.length !== 0) {
    isAddEquip.value = true;
  } else {
    formRef?.value.validateField("className");
    formRef?.value.validateField("inspectArea");
    formRef?.value.validateField("tableData");
  }
}
// 拖拽巡检设备
function tableEqiupDrag(evt) {
  const eqpData = cloneDeep(tableEqiupSelected.value);
  const oldItem = eqpData[evt.oldIndex];
  eqpData.splice(evt.oldIndex, 1);
  eqpData.splice(evt.newIndex, 0, oldItem);
  tableEqiupSelected.value = cloneDeep(eqpData);
}
// 移除巡检设备
function deleteEquipSelected(row) {
  tableEqiupSelected.value = tableEqiupSelected.value.filter(item => item["eqpId"] !== row["eqpId"]);
  // 内容改变，清空ruleContent
  ruleContent.value = null;
}
//设备选择
function selectEquipItems(val) {
  tableEqiupSelected.value = mergeAndDeduplicate(tableEqiupSelected.value || [], val, "eqpId");
  // 内容改变，清空ruleContent
  ruleContent.value = null;
  if (tableEqiupSelected.value.length > 0) {
    formRef?.value.clearValidate("taskEqpRelationDTOS");
  }
}
function mergeAndDeduplicate(arr1, arr2, key) {
  const map = new Map();
  // 合并两个数组
  const combinedArray = [...arr1, ...arr2];
  // 遍历合并后的数组，并根据 key 去重
  combinedArray.forEach(item => {
    map.set(item[key], item);
  });
  // 将 Map 转换回数组
  return Array.from(map.values());
}
// 筛选去除非必要条件
const filterParams = params => {
  const newParams = {};
  Object.keys(INSPECT_RULE_DEFAULT_FORMVALUE).forEach(key => {
    newParams[key] = params[key];
  });
  return newParams;
};
const contentDTOListForEach = (ruleContentItemDTOList, contentDTOList, data = {}) => {
  contentDTOList.forEach(contentDTOItem => {
    const { contentItemDTOList, ...others } = contentDTOItem;
    contentItemDTOList?.forEach(contentItemDTOItem => {
      if (data.inspectContentType === 1 && contentItemDTOItem.eqpStatusList) {
        const { eqpStatusList } = contentItemDTOItem;
        contentItemDTOItem.eqpStatusList = eqpStatusList.map(item => item.value);
      }
      ruleContentItemDTOList.push({
        ...contentItemDTOItem,
        ...others,
        inspectEqpId: contentItemDTOItem.eqpId,
        inspectRuleCode: formValue.value.ruleCode,
        inspectArea: formValue.value.inspectArea,
        ...data
      });
    });
  });
};
// 生成巡检规则巡检项
const getRuleContentItemDTOList = () => {
  const ruleContentItemDTOList = [];
  const { contentDTOList, eqpContentDTOList } = ruleContent.value;
  if (contentDTOList) {
    // 环境巡检
    contentDTOListForEach(ruleContentItemDTOList, contentDTOList, { inspectContentType: 2 });
  }
  if (eqpContentDTOList) {
    // 设备巡检
    eqpContentDTOList.forEach(eqpContentDTOItem => {
      const { eqpId, contentDTOList } = eqpContentDTOItem;
      contentDTOListForEach(ruleContentItemDTOList, contentDTOList, { inspectContentType: 1, inspectEqpId: eqpId, eqpId: eqpId });
    });
  }
  return ruleContentItemDTOList;
};
const getIds = (obj, arr = []) => {
  if (obj) {
    if (obj.children) {
      obj.children.forEach(item => {
        getIds(item, arr);
      });
    } else {
      arr.push(obj.id);
    }
  }
  return arr;
};
const findInspectArea = (inspectArea, positionCodesList) => {
  for (let index = 0; index < positionCodesList.length; index++) {
    const element = positionCodesList[index];
    if (element.id === inspectArea) {
      return element;
    }
    if (element.children) {
      const childrenElement = findInspectArea(inspectArea, element.children);
      if (childrenElement) {
        return childrenElement;
      }
    }
  }
};
const getInspectAreaCodes = inspectArea => {
  let obj = findInspectArea(inspectArea, positionCodesList.value);
  const arr = getIds(obj);
  return arr;
};
// 保存基础信息、巡检内容
const handleSubmit = async (formEl: any) => {
  if (!formEl) return;
  await formEl.validate(async valid => {
    if (valid) {
      // 巡检内容保存
      const { path } = route;
      const { id, ...others } = formValue.value;
      const params = filterParams(others);
      if (!ruleContent.value) {
        PxMessage.warning("正在获取巡检规则预览内容，请稍后保存");
      }
      const ruleContentItemDTOList = getRuleContentItemDTOList();
      // 新增与复制页面提交
      if (path === "/all/equip/inspect/rule/add" || path === "/all/equip/inspect/rule/copy") {
        await saveInspectRule({
          ...params,
          inspectTemCodeList: inspectTemCodeList.value,
          eqpIdList: eqpIdList.value,
          ruleContentItemDTOList
        });
      }
      // 编辑页面提交
      if (path === "/all/equip/inspect/rule/edit") {
        await updateInspectRule({
          id,
          ...params,
          inspectTemCodeList: inspectTemCodeList.value,
          eqpIdList: eqpIdList.value,
          ruleContentItemDTOList
        });
      }
      PxMessage.success("保存成功");
      router.push("/all/equip/inspect/rule");
    } else {
      PxMessage.error("表单校验未通过，请检查");
    }
  });
};
// 返回主页面
const cancelMainPage = () => {
  PxMessageBox.confirm("确认退出页面？退出后内容不会保存", "提示", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
    draggable: true
  })
    .then(async () => {
      resetManagePage();
    })
    .catch(() => {});
};
// 清空指定字段
const clearFields = (keys: string[]) => {
  keys.forEach(item => {
    formValue.value[item] = INSPECT_RULE_DEFAULT_FORMVALUE[item];
  });
  if (keys.includes("tableData")) {
    tableData.value = [];
  }
  if (keys.includes("tableEqiupSelected")) {
    tableEqiupSelected.value = [];
  }
};
// 清空全部数据
const resetManagePage = () => {
  formRef.value?.resetFields();
  actions.back();
};
</script>
<style lang="scss" scoped>
@import url("@/views/all/equip/scss/add-detail.scss");

.add-equip-detail {
  .add-equip-content {
    height: calc(100vh - 200px);

    .px-steps--simple {
      padding: 13px 22%;
    }

    .inspect-table-view {
      .px-form-item {
        margin-bottom: 0;
      }
    }

    .inspect-table-edit {
      .px-form-item {
        padding-top: 16px;
      }

      .px-table__cell {
        padding: 0;
      }

      .px-form-item__content {
        padding-top: 16px;
      }

      :deep(.px-table__header) {
        .must::before {
          margin-right: 4px;
          color: var(--px-color-danger);
          content: "*";
        }
      }
    }
  }

  .add-equip-body {
    height: calc(100vh - 278px);
  }
}
</style>
